<template>
    
</template>
<script setup lang="ts">
import pinyin from 'pinyin' ;
import {onMounted,ref,watch} from "vue"
import {
  ConnectionQuality,
  ConnectionState,
  DisconnectReason,
  ExternalE2EEKeyProvider,
  LocalAudioTrack,
  LocalParticipant,
  LogLevel,
  MediaDeviceFailure,
  Participant,
  ParticipantEvent,
  RemoteParticipant,
  RemoteTrack,
  RemoteTrackPublication,
  RemoteVideoTrack,
  Room,
  RoomConnectOptions,
  RoomEvent,
  RoomOptions,
  ScreenSharePresets,
  Track,
  TrackPublication,
  VideoCaptureOptions,
  VideoCodec,
  VideoPresets,
  VideoQuality,
  createAudioAnalyser,
  setLogLevel,
  supportsAV1,
  supportsVP9,
  LocalTrackPublication,
} from 'livekit-client';
import { DataTopic,sendMessage,DataCommand } from './message'
import {getCurrentInstance} from "vue";
import {componentTypes, mittTypes} from "@/util/types"
import { useSceneStore } from '@/stores/scene';
import {getMinioTtsAudioFile} from "@/api/apiRequst"
import {uuid,unicodeToString} from '@/util/common.js'
import {sendMessageToParent} from "@/util/common.js"
import {getUrlParam} from "@/util/common.js"
import {ElMessage} from "element-plus";
const sceneStore = useSceneStore()

const { appContext : { config: { globalProperties } } } = getCurrentInstance();

const internalInstance = getCurrentInstance()
const emitter = internalInstance.appContext.config.globalProperties.emitter

let muteVideo = false;

const props = defineProps({
  url: String,
  token: String,
  currentProjectType: String,
})

var livekitRoom;
const appActions = {
  connectToRoom :async (
    url: string,
    token: string,
  ): Promise<Room | undefined> => {
      // creates a new room with options
      livekitRoom = new Room({
      // automatically manage subscribed video quality
      // adaptiveStream: true,
    
      // optimize publishing bandwidth and CPU for published tracks
      dynacast: true,
    
      // default capture settings
      videoCaptureDefaults: {
        resolution: VideoPresets.h720.resolution,
      },
      publishDefaults: {
        dtx: false,
       
        red: true,
      },
      adaptiveStream: { pixelDensity: 'screen' },
      // dynacast: true,
      
    });

      var startTime = Date.now();
      await livekitRoom.prepareConnection(url, token);
      const prewarmTime = Date.now() - startTime;
      console.log(`prewarmed connection in ${prewarmTime}ms`);

      livekitRoom
        .on(RoomEvent.ParticipantConnected, participantConnected)
        .on(RoomEvent.DataReceived, handleData)
        .on(RoomEvent.Disconnected, handleRoomDisconnect)
        .on(RoomEvent.Reconnecting, () => console.log('Reconnecting to room'))
        .on(RoomEvent.Reconnected, async () => {
          console.log(
            'Successfully reconnected. server',
            await livekitRoom.engine.getConnectedServerAddress(),
          );
        })
        .on(RoomEvent.LocalTrackPublished, (pub) => {
          const track = pub.track as LocalAudioTrack;

          if (track instanceof LocalAudioTrack) {
            const { calculateVolume } = createAudioAnalyser(track);
            setInterval(() => {
              if(microphoneStatus){
                sendMessageToParent('livekit-event','volume',{volume:calculateVolume().toFixed(4)})
              }
              // console.log('local-volume', calculateVolume().toFixed(4));
              // $('local-volume')?.setAttribute('value', calculateVolume().toFixed(4));
              emitter.emit(mittTypes.CHATBOX.UPDATE_CHATBOX_VOLUME,calculateVolume().toFixed(4))
            }, 200);
          }

        })
        .on(RoomEvent.LocalTrackUnpublished, handleLocalTrackUnpublished)
        .on(RoomEvent.RoomMetadataChanged, (metadata) => {
          console.log('new metadata for room', metadata);
        })
        // .on(RoomEvent.MediaDevicesChanged, handleDevicesChanged)
        .on(RoomEvent.AudioPlaybackStatusChanged, () => {
          // if (room.canPlaybackAudio) {
          //   $('start-audio-button')?.setAttribute('disabled', 'true');
          // } else {
          //   $('start-audio-button')?.removeAttribute('disabled');
          // }
        })
        .on(RoomEvent.MediaDevicesError, (e: Error) => {
          const failure = MediaDeviceFailure.getFailure(e);
          console.log('media device failure', failure);
        })
        .on(
          RoomEvent.ConnectionQualityChanged,
          (quality: ConnectionQuality, participant?: Participant) => {
            console.log('connection quality changed', participant?.identity, quality);
          },
        )
        .on(RoomEvent.TrackSubscribed, (track, pub, participant) => {
          console.log('subscribed to track', pub.trackSid, participant.identity);
          // renderParticipant(participant);
          // renderScreenShare(room);
          
          if (track.kind === Track.Kind.Video || track.kind === Track.Kind.Audio) {
            // attach it to a new HTMLVideoElement or HTMLAudioElement
            const element = track.attach();
            // parentElement.appendChild(element);
          }
        })
        .on(RoomEvent.TrackUnsubscribed, (_, pub, participant) => {
          console.log('unsubscribed from track', pub.trackSid);
          // renderParticipant(participant);
          // renderScreenShare(room);
          // track.detach();
          
        })
        .on(RoomEvent.TranscriptionReceived, (_, pub, participant) => {
          console.log('TranscriptionReceived', pub);
          // renderParticipant(participant);
          // renderScreenShare(room);
          // track.detach();
          
        })
        .on(RoomEvent.SignalConnected, async () => {
          const signalConnectionTime = Date.now() - startTime;
          console.log(`signal connection established in ${signalConnectionTime}ms`);
          // speed up publishing by starting to publish before it's fully connected
          // publishing is accepted as soon as signal connection has established
          // await room.localParticipant.setMicrophoneEnabled(true);
            console.log(`tracks published in ${Date.now() - startTime}ms`);
          // if (shouldPublish) {
            await livekitRoom.localParticipant.setMicrophoneEnabled(true);
            console.log(`tracks published in ${Date.now() - startTime}ms`);
          //   // updateButtonsForPublishState();
          // }
        })
        .on(RoomEvent.ParticipantEncryptionStatusChanged, () => {
          // updateButtonsForPublishState();
        })
        .on(RoomEvent.TrackStreamStateChanged, (pub, streamState, participant) => {
          console.log(
            `stream state changed for ${pub.trackSid} (${
              participant.identity
            }) to ${streamState.toString()}`,
          );
        });
      
      try {
        // read and set current key from input
        // const cryptoKey = (<HTMLSelectElement>$('crypto-key')).value;
        // state.e2eeKeyProvider.setKey(cryptoKey);
        // if ((<HTMLInputElement>$('e2ee')).checked) {
        //   await room.setE2EEEnabled(true);
        // }
      
        await livekitRoom.connect(url, token);
        const elapsed = Date.now() - startTime;
        console.log(
          `****** successfully connected to ${livekitRoom.name} in ${Math.round(elapsed)}ms`,
          await livekitRoom.engine.getConnectedServerAddress(),
        );
        // activeReturn();
        // setTimeout(() => {
          
        // }, 2500);
        emitter.emit(mittTypes.CHATBOX.ADD_WAITING_MESSAGE);
        emitter.emit(mittTypes.LIVEKIT.CONNECT_SUCCESS);
        
        sceneStore.livekitRoom = livekitRoom;
        livekitRoom.remoteParticipants.forEach((participant) => {
          setTimeout(() => {
            participantConnected(participant);
          }, 1000);
         
        });
        //默认关闭 等待开始打开麦克风
        microphoneStatus = false
        await livekitRoom.localParticipant.setMicrophoneEnabled(false);
        //开始按钮点击后打开麦克风
        emitter.on(mittTypes.LOADING.START_SCENE,async function(){
          wakeupReturn()
          
          if(sceneStore.projectConfig.projectSet.platform == "guide"){
            // 讲解数字人嵌入大屏 默认打开麦克风
            microphoneStatus = true
            await livekitRoom.localParticipant.setMicrophoneEnabled(true);
          }else if(sceneStore.projectConfig.projectSet.platform == "screen"){
            //一体机端 网页浏览 只有语音控件 默认打开麦克风
            microphoneStatus = true
            await livekitRoom.localParticipant.setMicrophoneEnabled(true);
            
          }else if(sceneStore.projectConfig.projectSet.platform == "mobile"){
            if(sceneStore.projectConfig.uiConfig.chatbox.input.type == 'audio'&&sceneStore.projectConfig.uiConfig.chatbox.input.audioType == 'auto'){
              microphoneStatus = true
              await livekitRoom.localParticipant.setMicrophoneEnabled(true);
            }
          }else if(sceneStore.projectConfig.projectSet.platform == "pc"){
           if(sceneStore.projectConfig.uiConfig.chatbox.input.type == 'audio'&&sceneStore.projectConfig.uiConfig.chatbox.input.audioType == 'auto'){
              microphoneStatus = true
              await livekitRoom.localParticipant.setMicrophoneEnabled(true);
            }
          }

          const muteMic = getUrlParam('muteMic')
          if(muteMic == '1'){
            microphoneStatus = false
            await livekitRoom.localParticipant.setMicrophoneEnabled(false);
          }
          
        })
        
        
        // participantConnected(livekitRoom.localParticipant);
      } catch (error: any) {
        let message: any = error;
        if (error.message) {
          message = error.message;
        }
        console.log('could not connect:', message);
        return;
      }
  }
}

function handleLocalTrackUnpublished(
  publication: LocalTrackPublication,
  participant: LocalParticipant,
) {
  // when local tracks are ended, update UI to remove them from rendering
  // publication.track.detach();
}

function handleActiveSpeakerChange(speakers: Participant[]) {
  // show UI indicators when participant is speaking
}
function handleRoomDisconnect(speakers: Participant[]) {
  // show UI indicators when participant is speaking
  console.log('disconnected from room');
  /*ElMessage({
    message: '与服务器断开连接,请等待重新连接或尝试重新进入',
    type: 'error'
  });*/
}

 // 添加到aihumanChatManager类中
 async function driveDigitalHuman(audioData) {
    try {
      if(muteVideo){
        return ;
      }
      // 准备FormData
      const formData = new FormData();
      
      // 如果是Blob对象直接使用，如果是URL则需要先获取
      let audioBlob;
      if (audioData instanceof Blob) {
        audioBlob = audioData;
      } else {
        // 如果是URL，先获取音频数据
        const response = await fetch(audioData);
        audioBlob = await response.blob();
      }
      
      // 添加到表单
      formData.append('audio', audioBlob, 'recording.wav');
      
      // 发送请求到数字人驱动接口
      const response = await fetch(import.meta.env.MODE == 'development'?'':'https://aimeta.huilan.com:32109'+'/2dWebApi/audio', {
        method: 'POST',
        body: formData
      });
      
      if (!response.ok) {
        throw new Error(`驱动数字人失败: ${response.status} ${response.statusText}`);
      }
      
      const result = await response.json();
      console.log('数字人驱动成功:', result);
      
    } catch (error) {
      console.error('驱动数字人出错:', error);
    }
  }

// 文字驱动数字人方法
async function driveDigitalHumanByText(text, mode = 'echo', interrupt = false) {
  try {
    // 构建请求参数
    const requestData = {
      text: text,
      type: mode, // 'chat'或'echo'
      interrupt: true,
      disrupt:false
    };
    
    // 发送请求到数字人驱动接口
    const response = await fetch(import.meta.env.MODE == 'development'?'':'https://aimeta.huilan.com:32109'+'/2dWebApi/human', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(requestData)
    });
    
    if (!response.ok) {
      throw new Error(`文字驱动数字人失败: ${response.status} ${response.statusText}`);
    }
    
    const result = await response.json();
    console.log('文字驱动数字人成功:', result);
    return result;
    
  } catch (error) {
    console.error('文字驱动数字人出错:', error);
    throw error;
  }
}
const audioQueue = ref([]) // 用于存储待处理的音频队列
let isProcessing = ref(false) // 标记是否正在处理队列
let shouldStop = ref(false) // 标记是否需要停止处理
// 处理音频队列的函数
async function processAudioQueue() {
  if (isProcessing.value || audioQueue.value.length === 0) return
  
  isProcessing.value = true
  while (audioQueue.value.length > 0 && !shouldStop.value) {
    const currentItem = audioQueue.value[0]
    try {
      const audioFile = await getMinioTtsAudioFile({
        object_name: currentItem.objectName,
      })
      const blob = new Blob([audioFile], { type: 'audio/wav' })
      const localUrl = (window.URL || webkitURL).createObjectURL(blob)
      
      currentItem.temp.data[0].speechWordsList[0].timelineData.speechData[0].src = localUrl
      currentItem.temp.data[0].speechWordsList[0].timelineData.id = uuid()
      currentItem.temp.data[0].type = 'dynamic'
      currentItem.temp.data[0].speechWordsList[0].timelineData.actions.forEach((action:any, index:number) => {
        action.effectId = componentTypes.FLOW_EDIT.SPEECH
        action.id = uuid()
        action.data.type = 'dynamic'
        action.data.src = localUrl
        action.data.objectName = currentItem.objectName
        action.data.visemeIndex = 0
        if(index == currentItem.temp.data[0].speechWordsList[0].timelineData.actions.length-1){
          action.data.lastWord = true
        }
      })

      if(audioQueue.value.length > 0 &&props.currentProjectType == 'UE3d' ) {
        multiDataToShow = currentItem.temp
      } else if(audioQueue.value.length > 0 &&props.currentProjectType == '2d'){
        //driveDigitalHumanByText('')
        driveDigitalHuman(blob)
        emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE, currentItem.temp.data[0])
      }
      else if(audioQueue.value.length > 0 &&props.currentProjectType == 'Web3d') {
        emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE, currentItem.temp.data[0])
      }
    } catch (error) {
      console.error('处理音频失败:', error)
    }
    audioQueue.value.shift()
  }
  isProcessing.value = false
  shouldStop.value = false
}

// 当前麦克风状态
let microphoneStatus = true;
//ue端等待ue语音加载完开始播放再播放流程节点内容
let multiDataToShow = null;
//用于监听停止回答按钮 根据segmentid阻止后续相同id消息播放
// let multiDataPlayingSegmentId = null;
let multiDataStopSegmentId = null;
//监听ue是否多模态消息播放完毕
let ueMultiDataPlaying = false;
let ueMultiDataTimeout = null;
async function handleData(msg: Uint8Array, participant?: RemoteParticipant,kind?:0,topic?:string) {

  // const chat = <HTMLTextAreaElement>$('chat');
  let from = 'server';
  if (participant) {
    from = participant.identity;
  }
  console.log('from',from);
  console.log('topic',topic);
 
  const decoder = new TextDecoder();
  if(topic==DataTopic.CHAT){
    //聊天数据
    console.log("msg:",msg);
    
    let decodeMsg= decoder.decode(msg);
    // console.log(decodeMsg);
    console.log(decodeMsg);
    let temp ;
    temp=JSON.parse(decodeMsg);
    console.log(from,temp);
    // // chat.value += `${from}: ${str}\n`;
    // chat.value += `${from}: ${temp.message}\n`;
    // chatList.data.push({
    //   text: temp.message,
    //   dir: 'left',
    //   type: 'text'
    // } as never)
    if(!sceneStore.isSleeping){
      // 非睡眠时才显示消息
      if(from == 'agent'){
        if(temp.message.indexOf('<|INTERRUPT|>')>-1){
          //打断信息
        }else if(temp.message.indexOf('<|STT|>')>-1){
          // tts
        }
        else{
          console.log(unicodeToString(temp.message));
          let thinkMessage = unicodeToString(temp.message)
          if(thinkMessage.indexOf('<think>')>-1){
            emitter.emit(mittTypes.CHATBOX.ADD_THINK_MESSAGE,thinkMessage)
          }
          
          // emitter.emit(mittTypes.LIVEKIT.MESSAGE_CHAT_RECIVE,{
          //   messageData:temp,
          //   from : mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.BOT
          // })
        }
        
      }
      
      // 更新非睡眠状态
      emitter.emit(mittTypes.SLEEPING_CONTROL.UPDATE_WAKEUP_STATUS)
    }
    

  }else if(topic == DataTopic.CHAT_UPDATE){

    //聊天数据流式更新
    let decodeMsg= decoder.decode(msg);
    // console.log(decodeMsg);
    console.log(decodeMsg);
    let temp ;
    temp=JSON.parse(decodeMsg);
    // console.log(from,temp);
    if(!sceneStore.isSleeping){
      // 非睡眠时才显示消息
      if(temp.message.indexOf('<|INTERRUPT|>')>-1){
        //打断信息
      }else{
        console.log(unicodeToString(temp.message));
        let thinkMessage = unicodeToString(temp.message)
        if(thinkMessage.indexOf('<think>')>-1){
          emitter.emit(mittTypes.CHATBOX.ADD_THINK_MESSAGE,thinkMessage)
        }
        // 聊天信息
        // emitter.emit(mittTypes.LIVEKIT.MESSAGE_CHAT_UPDATE,{
        //   messageData:temp,
        //   from : mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.BOT
        // })
      }
      
       // 更新非睡眠状态
       emitter.emit(mittTypes.SLEEPING_CONTROL.UPDATE_WAKEUP_STATUS)
    }
    
  }else if(topic==DataTopic.VISEME){//表情数据
    let decodeMsg= decoder.decode(msg);
    let temp ;
    temp=JSON.parse(decodeMsg);
    console.log(temp);
    let msgfrom = from=='agent'?mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.BOT:mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.LOCAL
    if(!sceneStore.isSleeping){
      // 非睡眠时才显示消息
      emitter.emit(mittTypes.LIVEKIT.MESSAGE_VISEME_RECIVE,{
        messageData:temp,
        from : msgfrom
      })
    }
    
    // chat.value += `${from} 表情: ${temp.message}\n`;
  
    //告诉服务器收到口型数据 播放音频
    if(from == 'agent'){
      // let message = JSON.parse(temp.message)
      // sckReturn(message.request_id,message.segment_id);
    }
    
    // sceneStore.npcRole.speak(tringChatMessage)
  }else if(topic==DataTopic.FLOWNODE_DATA){
   
    // sceneStore.isSleeping = false;
    // 非睡眠时才显示消息
    let decodeMsg= decoder.decode(msg);
    let temp ;
    temp=JSON.parse(decodeMsg);
    let decodeMsgData=JSON.parse(decodeMsg);
    console.log('flownode_data:',temp);
    if(temp.data[0].sleepWord){
      //休眠后返回消息为睡眠内容 应为结束语 
      emitter.emit(mittTypes.CHATBOX.STOP_REPLY)
      return;
    }
    // console.log('flownode_data:',temp.data[0].speechWordsList[0].timelineData.speechData[0].text);
    let type=temp.type;
    let localUrl,objectName;
    // multiDataPlayingSegmentId = temp.segmentId
    // if(multiDataPlayingSegmentId == multiDataStopSegmentId){
    //   // 已被停止回答按钮停止的后续消息
    //   return;
    // }
    
    if(type=='static'){//流程中静态数据,yang 1227
      let staticData
      sceneStore.projectConfig.flowNodeConfig.forEach(element => {
        if(element.id == temp.data[0].id){
          staticData = element;
        }
      });
      localUrl=staticData.speechWordsList[0].timelineData.speechData[0].src;
      temp.data[0] = staticData;
      temp.data[0].type = 'static';
      if(props.currentProjectType == 'UE3d'){
        // 接收多模态数据等待playing消息再进行播放
        multiDataToShow = temp
        if(sceneStore.projectConfig.projectSet.platform != "guide"){
          //统一由前端收到后 发送ue多模态数据 讲解数字人需判断是否移动后发送 其他数字人直接发送
          driveUeMutiDataReturn(temp)
        }else{
          emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE, temp.data[0]);
        }
        
      }else if(props.currentProjectType == 'Web3d'){
        // sceneStore.timelineRef.
        emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE,temp.data[0])
      }
      // 获取音频文件并驱动数字人
      if(props.currentProjectType == '2d'){
        driveDigitalHumanByText('')
        emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE,temp.data[0])
        driveDigitalHuman(localUrl);
         
      }
    }else if(type=='dynamic'){
      temp.data[0].id = decodeMsgData.requestId
      if(props.currentProjectType == 'UE3d'){
        // 接收多模态数据等待playing消息再进行播放
        multiDataToShow = temp
        //统一由前端收到后 发送ue多模态数据 
        driveUeMutiDataReturn(temp)
        
      }else{
        //tts动态结果
        objectName = temp.data[0].speechWordsList[0].timelineData.speechData[0].audio.object_name;
        // 将任务添加到队列
        audioQueue.value.push({
          temp,
          objectName
        })
        shouldStop.value = false
        // 开始处理队列
        processAudioQueue()
      }
      
      
    }
  
    // const localUrl ='https://ai3d.huilan.com/PeachBanquet/backend/api/TTSAudio?audio_id='+objectName+'&raw=false' 
   
    
    let text = ''
    temp.data[0].speechWordsList[0].timelineData.speechData.forEach((speechData:any,index:number)=>{
      text += speechData.text
    })
      // 聊天信息显示
    emitter.emit(mittTypes.LIVEKIT.MESSAGE_CHAT_RECIVE,{
      messageData:{
        message:text,
        id:temp.requestId
      },
      from : mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.BOT
    })
    // 更新非睡眠状态
    emitter.emit(mittTypes.SLEEPING_CONTROL.UPDATE_WAKEUP_STATUS)
  }else if(topic == DataTopic.MULTI_MODAL_DATA_PLAYING){
    let decodeMsg= decoder.decode(msg);
    let decodeMsgData=JSON.parse(decodeMsg);
    console.log('multi_modal_data_playing:', decodeMsgData);
    if(props.currentProjectType == 'UE3d'){
      if(decodeMsgData.data == '<start>'){
        // 收到播放指令 播放对应的多模态数据
        if(multiDataToShow&&(multiDataToShow.requestId == decodeMsgData.request_id)){
          const multiData = multiDataToShow.data[0]
          multiDataToShow = null;
          emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE,multiData)
        }
        // emitter.emit(mittTypes.RENDERER.SET_UE_FLOWNODE_LIST_START)
        ueMultiDataPlaying = true;
        clearTimeout(ueMultiDataTimeout)
      }else if(decodeMsgData.data == '<end>'){
        ueMultiDataPlaying = false;
        ueMultiDataTimeout = setTimeout(() => {
          if(!ueMultiDataPlaying){
            emitter.emit(mittTypes.RENDERER.SET_UE_FLOWNODE_LIST_END)
          }
        }, 1000);
        
      }
      
      
    }
  }
  else if(topic==DataTopic.STT){
    //识别一句话后表示已提问 禁止麦克风 等这句话回复结束再恢复
    // emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE, false)
      
    //用户自己的麦克风声音插入到对话列表中
    let decodeMsg= decoder.decode(msg);
    console.log('asr:'+ decodeMsg);
    sceneStore.currentQuestion = decodeMsg
    sceneStore.currentQuestionType = 'stt'
    
    shouldStop.value = false
    
    emitter.emit(mittTypes.RENDERER.CLEAR_FLOWNODE)
    emitter.emit(mittTypes.WEBHUMAN.STOP_VISEME_AUDIO)
    multiDataToShow = null;
    //判断唤醒词和睡眠词
    let wake = false
    let sleep = false
    let pinyindecodeMsg = pinyin(decodeMsg.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, ""), {
      style: pinyin.STYLE_NORMAL, // 设置拼音样式为普通风格
      heteronym: false // 不考虑多音字
    }).join('-')
    console.log('pinyindecodeMsg:',pinyindecodeMsg)
    
    if(sceneStore.projectConfig.wakeConfig.wakeParams.wakeWord instanceof Array){
      //数组形式的唤醒词休眠词
      let wakeWord =''
      if(sceneStore.projectConfig.wakeConfig.wakeParams.wakeWord.length >0){
        wakeWord = sceneStore.projectConfig.wakeConfig.wakeParams.wakeWord.length[0]
      }
      sceneStore.projectConfig.wakeConfig.wakeParams.wakeWord.forEach((wakeWord,index) => {
        let pinyinwakeWord = pinyin(wakeWord.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, ""), {
          style: pinyin.STYLE_NORMAL, // 设置拼音样式为普通风格
          heteronym: false // 不考虑多音字
        }).join('-')
        if(pinyindecodeMsg == pinyinwakeWord){
          wake = true
        }
      });
      sceneStore.projectConfig.sleepConfig.sleepParams.sleepWord.forEach(sleepWord => {
        let pinyinsleepWord = pinyin(sleepWord.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, ""), {
            style: pinyin.STYLE_NORMAL, // 设置拼音样式为普通风格
            heteronym: false // 不考虑多音字
        }).join('-')
        if(pinyindecodeMsg == pinyinsleepWord){
          sleep = true
        }
      });
      
    }else{
     
      let pinyinwakeWord = pinyin(sceneStore.projectConfig.wakeConfig.wakeParams.wakeWord.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, ""), {
        style: pinyin.STYLE_NORMAL, // 设置拼音样式为普通风格
        heteronym: false // 不考虑多音字
      }).join('-')
      wake = (pinyindecodeMsg == pinyinwakeWord)
      console.log('pinyinwakeWord:',pinyinwakeWord)

      let sleepword = sceneStore.projectConfig.sleepConfig.sleepParams.sleepWord
      if(!sleepword){
        sleepword = ''
      }
      let pinyinsleepWord = pinyin(sleepword.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, ""), {
          style: pinyin.STYLE_NORMAL, // 设置拼音样式为普通风格
          heteronym: false // 不考虑多音字
      }).join('-')
      sleep = (pinyindecodeMsg == pinyinsleepWord)
      console.log('pinyinsleepWord:',pinyinsleepWord)
    }

    if(wake ){
     
      if(sceneStore.isSleeping){
      
        // //发送唤醒消息
        //agent端处理 无需前端返回了
        // emitter.emit(mittTypes.SLEEPING_CONTROL.WAKEUP);
        
        emitter.emit(mittTypes.LIVEKIT.MESSAGE_CHAT_RECIVE,{
          messageData:{message:decodeMsg.replace(/[\u3002\uff1b\uff0c\u3001\uff0e\u2026\u201c\u201d\u2018\u2019]\s*$/, '')},
          from : mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.LOCAL,
          wakeOrsleepWord:false,
        })
      }else{
        // 非睡眠时才显示消息
        emitter.emit(mittTypes.LIVEKIT.MESSAGE_CHAT_RECIVE,{
          messageData:{message:decodeMsg.replace(/[\u3002\uff1b\uff0c\u3001\uff0e\u2026\u201c\u201d\u2018\u2019]\s*$/, '')},
          from : mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.LOCAL
        })
        
      }

      
    }else if(sleep ){
      if(!sceneStore.isSleeping){
        // 进入睡眠
        emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE_AGENT,false)
        // agent端处理 无需前端返回了
        // emitter.emit(mittTypes.SLEEPING_CONTROL.SLEEP);
        emitter.emit(mittTypes.LIVEKIT.MESSAGE_CHAT_RECIVE,{
          messageData:{message:decodeMsg.replace(/[\u3002\uff1b\uff0c\u3001\uff0e\u2026\u201c\u201d\u2018\u2019]\s*$/, '')},
          from : mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.LOCAL,
          wakeOrsleepWord:true,
        })
      }
      
    }else if(!sceneStore.isSleeping){
      // 非睡眠时才显示消息
      emitter.emit(mittTypes.LIVEKIT.MESSAGE_CHAT_RECIVE,{
        messageData:{message:decodeMsg.replace(/[\u3002\uff1b\uff0c\u3001\uff0e\u2026\u201c\u201d\u2018\u2019]\s*$/, '')},
        from : mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.LOCAL
      })
    }
    // chat.value += `用户 asr: ${decodeMsg}\n`;
  }else if(topic==DataTopic.INTERRUPT){
    // 打断消息
    let decodeMsg= decoder.decode(msg);
    console.log('interrupt:'+ decodeMsg);
    emitter.emit(mittTypes.RENDERER.CLEAR_FLOWNODE)
    emitter.emit(mittTypes.WEBHUMAN.STOP_VISEME_AUDIO)
    multiDataToShow = null;
  }else if(topic==DataTopic.AGENT_STATE_SYNC){
    // 同步agent休眠状态
    let decodeMsg= decoder.decode(msg);
    console.log('agent_state_sync:'+ decodeMsg);
    let msgData=JSON.parse(decodeMsg);
    if(msgData.data == '<activity>'){
      sceneStore.isSleeping = false;
      emitter.emit(mittTypes.SLEEPING_CONTROL.WAKEUP,true);
    }else if(msgData.data == '<hibernation>'){
      emitter.emit(mittTypes.SLEEPING_CONTROL.SLEEP,true);
    }
  }else if(topic == DataTopic.STOP_PLAY){
    emitter.emit(mittTypes.CHATBOX.STOP_REPLY)
    emitter.emit(mittTypes.LIVEKIT.STOP_REPLY)
    if(sceneStore.projectConfig.uiConfig.interrupt.interruptResponses.length > 0){
      let random = Math.floor(Math.random() * sceneStore.projectConfig.uiConfig.interrupt.interruptResponses.length);
      emitter.emit(mittTypes.RENDERER.SET_FLOWNODE,sceneStore.projectConfig.uiConfig.interrupt.interruptResponses[random].flowNode)
      emitter.emit(mittTypes.CHATBOX.ADD_MESSAGE,sceneStore.projectConfig.uiConfig.interrupt.interruptResponses[random].text)
      if(props.currentProjectType == '2d'){
        let localUrl=sceneStore.projectConfig.uiConfig.interrupt.interruptResponses[random].flowNode.speechWordsList[0].timelineData.speechData[0].src;
        driveDigitalHuman(localUrl)
        
      }
    }

  }else if(topic == DataTopic.ERROR){
    // emitter.emit(mittTypes.CHATBOX.STOP_REPLY)
    let decodeMsg= decoder.decode(msg);
    console.log('agent_state_sync:'+ decodeMsg);
    let msgData=JSON.parse(decodeMsg);
    console.log('livekit_error:'+ msgData);
  
  }else if(topic == DataTopic.CONTROLLER_COMMAND){
    // 控制器命令处理
    let decodeMsg = decoder.decode(msg);
    console.log('controller_command:' + decodeMsg);
    let msgData = JSON.parse(decodeMsg);
    
    handleControllerCommand(msgData);
  }
}

// 处理控制器命令
function handleControllerCommand(commandData: any) {
  const { command, data } = commandData;
  
  let success = false;
  let resultData = null;
  
  try {
    switch (command) {
      case DataCommand.PLAY_FLOW_NODE:
        // 播放指定流程节点
        if (data && data.nodeId) {
          emitter.emit(mittTypes.RENDERER.PLAY_FLOWNODE, {id:data.nodeId})
          success = true;
          resultData = { nodeId: data.nodeId };
        } else {
          throw new Error('缺少nodeId参数');
        }
        break;
      case DataCommand.TEXT_CHAT:
        // 播放指定流程节点
        if (data && data.message) {
          const options={
            topic: DataTopic.CHAT,
            reliable: true,
            // destinationIdentities:[]
          }
          sendMessage(livekitRoom.localParticipant,data.message,options);
          if(!sceneStore.isSleeping){
            // 更新非睡眠状态
            emitter.emit(mittTypes.SLEEPING_CONTROL.UPDATE_WAKEUP_STATUS)
          }
          success = true;
          resultData = { nodeId: data.nodeId };
        } else {
          throw new Error('缺少nodeId参数');
        }
        break;
      default:
        console.warn('未知的控制器命令:', command);
        resultData = { error: '未知的控制器命令' };
    }
  } catch (error) {
    console.error('处理控制器命令时出错:', error);
    resultData = { error: error.message };
    success = false;
  }
  
  // 发送确认消息
  sendControllerCommandAck(command, success, resultData);
}



function participantConnected(participant: Participant) {
  // appendLog('participant', participant.identity, 'connected', participant.metadata);
  console.log('participantConnected tracks ', participant.trackPublications);
  participant
    .on(ParticipantEvent.TrackMuted, (pub: TrackPublication) => {
      // appendLog('track was muted', pub.trackSid, participant.identity);
      // renderParticipant(participant);
    })
    .on(ParticipantEvent.TrackUnmuted, (pub: TrackPublication) => {
      // appendLog('track was unmuted', pub.trackSid, participant.identity);
      // renderParticipant(participant);
    })
    .on(ParticipantEvent.IsSpeakingChanged, () => {
      // renderParticipant(participant);
      emitter.emit(mittTypes.LIVEKIT.PATICIPANT_SPEAKING,participant)
    })
    .on(ParticipantEvent.ConnectionQualityChanged, () => {
      // renderParticipant(participant);
    });
    if (!(participant instanceof LocalParticipant)) {
      //web静音
      // if(props.currentProjectType != 'UE3d'){
      //   participant.setVolume(0);
      // }
      participant.setVolume(0);
      
      // const micPub = participant.getTrackPublication(Track.Source.Microphone);
      // micPub.disabled = true;
      // micPub.audioTrack.isMuted = true;
      // const audioELm = document.createElement('audio')
      // //ue静音
     
      // // don't attach local audio
      // audioELm.onloadeddata = () => {
      //   // if (participant.joinedAt && participant.joinedAt.getTime() < startTime) {
      //   //   const fromJoin = Date.now() - startTime;
      //   //   appendLog(`RemoteAudioTrack ${micPub?.trackSid} played ${fromJoin}ms from start`);
      //   // }
      //   // console.log('audio')
      //   audioELm.muted = true;
      //   audioELm.volume = 0
      // };
      // micPub?.audioTrack?.attach(audioELm);
    }
}
function ueDriveReturn(flownodeData:any){
  if (!livekitRoom) return;
    let id = uuid();
    const startmessage={
      command:DataCommand.FLOWNODE_DATA,
      data: [
        flownodeData
      ],
      requestId:id+'_1',
      segmentId:id,
    }
    const options={
      topic:DataTopic.FLOWNODE_DATA,
      reliable: true,
      type:'topic'
      
      // destinationIdentities:[]
    }
    console.log('ueDrive return:',flownodeData)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);
}
function textDriveReturn(text:any){
  if (!livekitRoom) return;

    const startmessage={
      command:DataCommand.TEXT_DRIVE,
      data: {
        text:text,
        action:"no"
      }
    }
    const options={
      topic:DataTopic.TEXT_DRIVE,
      reliable: true,
      type:'topic'
      
      // destinationIdentities:[]
    }
    console.log('textdrive return:',text)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);
}
function ackReturn(request_id:any,segment_id:any){
  if (!livekitRoom) return;

    const startmessage={
      command:DataCommand.VISEME_ACK,
      data: "<start>",
      request_id:request_id,
      segment_id:segment_id,
    }
    const options={
      topic:DataTopic.VISEME,
      reliable: true,
      
      
      // destinationIdentities:[]
    }
    console.log('request_id:',request_id)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);
  

}
function wakeupReturn(){
  if (!livekitRoom) return;

    const flow_temp=sceneStore.projectConfig.flowConfig.id;
    
    const startmessage={
      command:DataCommand.WAKEUP,
      data: "<start>",
      flow_first: true,
      flow_node_name:'',
      flow_template_id:flow_temp,
    }
    const options={
      topic:DataTopic.WAKEUP,
      reliable: true,
      
      // destinationIdentities:[]
    }
    console.log('wakeupReturn',startmessage,options)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);
    
}
function sleepReturn(){
  if (!livekitRoom) return;

    const flow_temp=sceneStore.projectConfig.flowConfig.id;
    
    const startmessage={
      command: DataCommand.AGENT_STATE_SYNC,
      data: "<hibernation>"
    }
    const options={
      topic:DataTopic.AGENT_STATE_SYNC,
      reliable: true,
      type:'topic'
      
      // destinationIdentities:[]
    }
    console.log('sleepReturn',startmessage,options)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);
    
}
function interruptReturn(){
  if (!livekitRoom) return;

    // 获取当前时间的时间戳（以毫秒为单位）
    let timestamp = Date.now();

    // 将毫秒转换为秒
    let seconds = Math.floor(timestamp / 1000);
    const startmessage={
      timestamp:seconds,
    }
    const options={
      topic:DataTopic.INTERRUPT,
      reliable: true,
      type:'topic'
      
      // destinationIdentities:[]
    }
    console.log('interruptReturn',startmessage,options)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);

    multiDataToShow = null;
    
}
function discontinueGenerateReturn(){
  if (!livekitRoom) return;

    // 获取当前时间的时间戳（以毫秒为单位）
    let timestamp = Date.now();

    // 将毫秒转换为秒
    let seconds = Math.floor(timestamp / 1000);
    const startmessage={
      timestamp:seconds,
    }
    const options={
      topic:DataTopic.DISCONTINUE_GENERATE,
      reliable: true,
      type:'topic'
      
      // destinationIdentities:[]
    }
    console.log('interruptReturn',startmessage,options)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);

    multiDataToShow = null;
    
}
function driveUeMoveReturn(command:any,data:any){
  if (!livekitRoom) return;

    const startmessage={
      command:command,
      data: data,
    }
    const options={
      topic:DataTopic.DRIVE_UE_MOVE,
      reliable: true,
      type:'topic'
      
      // destinationIdentities:[]
    }
    console.log('uemove_command:',command)
    console.log('uemove_data:',data)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);
}
function driveUeMutiDataReturn(data:any){
  if (!livekitRoom) return;

    const startmessage=data
    const options={
      topic:DataTopic.FLOWNODE_DATA,
      reliable: true,
      
      
      // destinationIdentities:[]
    }
    console.log('ue_Muti_data:',data)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);
}
// 发送控制器命令确认
function sendControllerCommandAck(command: string, success: boolean, data?: any) {
  if (!livekitRoom) return;

  const ackMessage = {
    command: 'controller_ack',
    data: {
      originalCommand: command,
      success: success,
      timestamp: Date.now(),
      ...(data && { details: data })
    }
  };
  
  const options = {
    topic: DataTopic.CONTROLLER_COMMAND,
    reliable: true,
    type: 'topic'
  };
  
  console.log('发送控制器确认:', ackMessage);
  sendMessage(livekitRoom.localParticipant, ackMessage, options, true);
}
function activeReturn(){
  if (!livekitRoom) return;

    const flow_temp=sceneStore.projectConfig.flowConfig.id;
    
    const startmessage={
      command: DataCommand.AGENT_STATE_SYNC,
      data: "<activity>"
    }
    const options={
      topic:DataTopic.AGENT_STATE_SYNC,
      reliable: true,
      type:'topic'
      
      // destinationIdentities:[]
    }
    console.log('activeReturn',startmessage,options)
  
    const tringStartMessage=sendMessage(livekitRoom.localParticipant,startmessage,options,true);
    
}


onMounted(async () => {
  var watchToken = watch(() => props.token, 
  (newVal, oldVal) => {
    // 逻辑
    if(props.token&&props.url){
      appActions.connectToRoom(props.url,props.token)
      emitter.on(mittTypes.LIVEKIT.DRIVE_UE_MOVE,function(data:any){
        driveUeMoveReturn(data.command,data.data)

      })
      emitter.on(mittTypes.LIVEKIT.DRIVE_UE_MULTIDATA,function(data:any){
        driveUeMutiDataReturn(data.data)

      })
      // 监听发送消息事件
      emitter.on(mittTypes.LIVEKIT.MESSAGE_SEND,function(message:any){
        const options={
            topic: DataTopic.CHAT,
            reliable: true,
            // destinationIdentities:[]
          }
          sendMessage(livekitRoom.localParticipant,message,options);
          if(!sceneStore.isSleeping){
            // 更新非睡眠状态
            emitter.emit(mittTypes.SLEEPING_CONTROL.UPDATE_WAKEUP_STATUS)
          }
        
      })
      // 监听发送文字直驱事件
      emitter.on(mittTypes.LIVEKIT.TEXT_DRIVE,function(message:any){
        textDriveReturn(message)
        
      })
      emitter.on(mittTypes.LIVEKIT.MESSAGE_VISEME_ACK_RETRUN,function(messageData:any){
        let msg = messageData
        ackReturn(msg.request_id,msg.segment_id);
        if(!sceneStore.isSleeping){
          // 更新非睡眠状态
          emitter.emit(mittTypes.SLEEPING_CONTROL.UPDATE_WAKEUP_STATUS)
        }
      })
      emitter.on(mittTypes.LIVEKIT.AUDIO_ENABLE,async function(enabled:any){
        microphoneStatus = enabled
        await livekitRoom.localParticipant.setMicrophoneEnabled(enabled);
        if(!sceneStore.isSleeping){
          // 更新非睡眠状态
          emitter.emit(mittTypes.SLEEPING_CONTROL.UPDATE_WAKEUP_STATUS)
        }
      })
      emitter.on(mittTypes.LIVEKIT.AUDIO_ENABLE_MOBILE,async function(enabled:any){
        microphoneStatus = enabled
        await livekitRoom.localParticipant.setMicrophoneEnabled(enabled);
        if(!sceneStore.isSleeping){
          // 更新非睡眠状态
          emitter.emit(mittTypes.SLEEPING_CONTROL.UPDATE_WAKEUP_STATUS)
        }
      })
      //收到唤醒指令
      emitter.on(mittTypes.LIVEKIT.WAKEUP_AGENT,async function(messageData:any){
        if(sceneStore.isSleeping){
          wakeupReturn()
        }
        
      })
      //收到唤醒指令
      emitter.on(mittTypes.LIVEKIT.INTERRUPT,async function(messageData:any){
        if(!sceneStore.isSleeping){
          interruptReturn()
        }
        
      })
      //收到停止回答指令
      emitter.on(mittTypes.LIVEKIT.STOP_REPLY,async function(messageData:any){
        if(!sceneStore.isSleeping){
          shouldStop.value = true
          audioQueue.value = [] // 清空队列
          // multiDataStopSegmentId = multiDataPlayingSegmentId
          discontinueGenerateReturn()
          if(props.currentProjectType == '2d'){
            driveDigitalHumanByText('');
          }
          
          
        }
        
      })
      // url驱动2d数字人
      emitter.on(mittTypes.LIVEKIT.DRIVE_2D_BY_URL,async function(messageData:any){
        driveDigitalHuman(messageData)
        
      })
      // 文字驱动2d数字人
      emitter.on(mittTypes.LIVEKIT.DRIVE_2D_BY_TEXT,async function(messageData:any){
        driveDigitalHumanByText(messageData)
        
      })
      // 驱动ue数字人
      emitter.on(mittTypes.LIVEKIT.DRIVE_UE_BY_FLOWNODE,async function(messageData:any){
        ueDriveReturn(messageData)
        
      })
      //收到睡眠指令
      emitter.on(mittTypes.LIVEKIT.SLEEP_AGENT,async function(messageData:any){
        if(sceneStore.isSleeping){
          sleepReturn()
        }
        
      })
      //收到睡眠指令
      emitter.on(mittTypes.LIVEKIT.SET_MULTIDATA,async function(messageData:any){
        if(!sceneStore.isSleeping){
          multiDataToShow = messageData.data;
          console.log('set-multiDataToShow',multiDataToShow)

        }
        
      })
      //睡眠时将agent静音
      emitter.on(mittTypes.LIVEKIT.AUDIO_ENABLE_AGENT,async function(enabled:any){
        livekitRoom.remoteParticipants.forEach((participant) => {
          if (!(participant instanceof LocalParticipant)) {
            if(enabled){
              // participant.setVolume(1);
            }else{
              participant.setVolume(0);
            }
          }
        });
      })
      emitter.on(mittTypes.TIMELINE.MUTE_AUDIO,function(){
        muteVideo = true;
      })
      emitter.on(mittTypes.TIMELINE.UNMUTE_AUDIO,function(){
        muteVideo = false;
      })
      watchToken()
    }
  },
  {deep: false, immediate: false})
    
    
})

// 暴露给外部调用的方法
const getMultiDataToShow = () => {
  console.log('multiDataToShow',multiDataToShow)
  return multiDataToShow;
}
// 暴露给外部调用的方法
const setMultiDataToShow = (data:any) => {
  console.log('set-multiDataToShow',data)
  multiDataToShow = data;
}

// 导出方法供外部使用
defineExpose({
  getMultiDataToShow,
  setMultiDataToShow
})
</script>
<script lang="ts">
export default {
  name: 'livekitManager'
}
</script>
<style scoped>

</style>